/*
  This example comes from a short article series in the Linux 
  Gazette by Richard A. Sevenich and Christopher Lopes, titled
  "Compiler Construction Tools". The article series starts at

  http://www.linuxgazette.com/issue39/sevenich.html

  Small changes and updates to newest JFlex+Cup versions 
  by Gerwin Klein
 */

/*
 Commented By: Christopher Lopes
 File Name: Main.java
 To Create: 
 After the scanner, lcalc.flex, and the parser, ycalc.cup, have been created.
 > javac Main.java

 To Run: 
 > java Main test.txt
 where test.txt is an test input file for the calculator.
 */

import java.io.*;
import java.util.*;

public class Main {

	public static void main(String[] args) {

		if (args.length != 1) {
			System.out.println("Forneca o nome do arquivo pelos arqumentos da chamada!");
			return;
		}

		String fileName = args[0];
		File file = new File(fileName);

		String msg = "Resultados para o arquivo: " + fileName;
		msg += System.lineSeparator();
		msg += System.lineSeparator();
		SemanticAnalyzer instance = SemanticAnalyzer.getInstance();
		try {
			PhpLexer lexer = new PhpLexer(new FileReader(file));
			lexer.setFileName(file.getName());
			PhpParser parser = new PhpParser(lexer);
			ParseNode rootNode = (ParseNode) parser.parse().value;

			if (!instance.validate()) {
				List<String> erros = instance.getErros();

				msg += "Erro Semantico";
				msg += System.lineSeparator();

				for (String s : erros) {
					if (s.contains("VariavelIndefinida:")) {
						String aux = s.replace("VariavelIndefinida:",
								"A variavel ");
						aux += " nao foi definida";
						msg += aux;
					} else {
						msg += s;
					}
					msg += System.lineSeparator();
				}

				System.out.println(msg);
			} else {
				System.out.println(System.lineSeparator());
				System.out.println(System.lineSeparator());
				System.out.println("Arquivo Valido!");
				System.out.println(System.lineSeparator());
				System.out.println(System.lineSeparator());

				TreeParser tp = new TreeParser(rootNode);
				tp.parse();
				System.out.println("== Codigo Assembly ==");
				System.out.println(System.lineSeparator());
				System.out.println(System.lineSeparator());

				System.out.println(tp.getCode());
			}

		} catch (Error e) {

			String mensagem = "Arquivo Invalido!";

			mensagem += System.lineSeparator();
			mensagem += System.lineSeparator();

			mensagem += "Erro Lexico/Sintatico";
			mensagem += System.lineSeparator();
			mensagem += System.lineSeparator();

			mensagem += trataExcecao(e.getMessage(), file.getAbsolutePath());

			System.out.println(msg + mensagem);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static String trataExcecao(String message, String filePath) {
		String retorno = "";

		String[] linhas = message.split("\\*\\*");
		int linha = Integer.parseInt(linhas[0]);
		int coluna = Integer.parseInt(linhas[1]);

		if (linha <= 0) {
			retorno += "Erro em linha indeterminada.";
			retorno += System.lineSeparator();
			retorno += "Checar fim de arquivo inesperado (esperando fechamento de parenteses, chaves ou aspas)";
			return retorno;
		}

		String format = "%" + (coluna - 1) + "s^";
		if (coluna == 1) {
			format = "%" + (coluna) + "s^";
		}

		try {
			Scanner sc = new Scanner(new File(filePath));
			for (int i = 0; i < linha - 1; i++) {
				sc.nextLine();
			}

			retorno += "Erro na linha " + linha + ".";
			retorno += System.lineSeparator();
			retorno += sc.nextLine();
			retorno += System.lineSeparator();
			retorno += String.format(format, " ");

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Error e) {

		}

		return retorno;
	}
}
